package com.itheima.stock.service.impl;

import com.google.common.collect.Lists;
import com.itheima.stock.config.vo.StockInfoConfig;
import com.itheima.stock.mapper.StockBlockRtInfoMapper;
import com.itheima.stock.mapper.StockBusinessMapper;
import com.itheima.stock.mapper.StockMarketIndexInfoMapper;
import com.itheima.stock.mapper.StockRtInfoMapper;
import com.itheima.stock.pojo.StockBlockRtInfo;
import com.itheima.stock.pojo.StockMarketIndexInfo;
import com.itheima.stock.pojo.StockRtInfo;
import com.itheima.stock.service.StockTimerTaskService;
import com.itheima.stock.utils.DateTimeUtil;
import com.itheima.stock.utils.IdWorker;
import com.itheima.stock.utils.ParseType;
import com.itheima.stock.utils.ParserStockInfoUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service("stockTimerTaskServiceImpl")
@Slf4j
public class StockTimerTaskServiceImpl implements StockTimerTaskService {
    @Autowired
    private StockInfoConfig stockInfoConfig;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;
    @Autowired
    private StockBusinessMapper stockBusinessMapper;
    @Autowired
    private ParserStockInfoUtil parserStockInfoUtil;
    @Autowired
    private StockRtInfoMapper stockRtInfoMapper;
    @Autowired
    private StockBlockRtInfoMapper stockBlockRtInfoMapper;
    @Override
    public void collectInnerMarketInfo() {
        //定义采集的url接口
        String url = stockInfoConfig.getMarketUrl()+String.join(",",stockInfoConfig.getInner());
        //调用restTmplate采集数据
        //组装请求头
        HttpHeaders headers = new HttpHeaders();
        headers.add("Referer","https://finance.sina.com.cn/stock/");//必须填写，否则数据加载不到
        headers.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
        //组装请求对象
        HttpEntity<Object> entity = new HttpEntity<>(headers);
        //发起请求
        String resString = restTemplate.postForObject(url, entity, String.class);
        //获取公共采集时间点
        Date date = DateTimeUtil.getDateTimeWithoutSecond(DateTime.now()).toDate();
        log.info("当前采集的数据:{}"+resString);
        //数据解析
        String reg = "var hq_str_(.+)=\"(.+)\";";
        //编译表达式,获取编译对象
        Pattern compile = Pattern.compile(reg);
        //匹配字符串
        Matcher matcher = compile.matcher(resString);
        List<StockMarketIndexInfo> list = new ArrayList<>();
        //判断是否有匹配的数值
        while (matcher.find()){
            //获取大盘的code码
            String group = matcher.group(1);
            //获取其他信息
            String[] group1 = matcher.group(2).split(",");
            //获取大盘指数
            String marketName = group1[0];
            //获取当前大盘的点数
            BigDecimal curPoint = new BigDecimal(group1[1]);
            //获取当前大盘的涨跌
            BigDecimal curPrice = new BigDecimal(group1[2]);
            //获取大盘的涨幅
            BigDecimal upDownRate = new BigDecimal(group1[3]);
            //获取成交量
            Long tradeVal = Long.valueOf(group1[4]);
            //获取成交金额
            Long treadeAmount = Long.valueOf(group1[5]);
            //组装entity对象
            StockMarketIndexInfo info = StockMarketIndexInfo.builder().id(idWorker.nextId() + "").markId(group)
                    .markName(marketName).curPoint(curPoint).currentPrice(curPrice)
                    .updownRate(upDownRate).tradeVolume(tradeVal).tradeAccount(treadeAmount).curTime(date).build();
            log.info("封装的对象信息:{}",info.toString());
            //收集封装的对象
            list.add(info);
        }
//        System.out.println(list);
        //批量插入
        stockMarketIndexInfoMapper.insertBatch(list);

    }

    @Override
    public void collectAshareInfo() {
        //获取所有的股票code集合 TODO 后期加入Redis缓存
        List<String> codelist = stockBusinessMapper.getStockCodelist();
        List<String> lists = codelist.stream().map(id -> {
            if (id.startsWith("6")) {
                id = "sh" + id;
            } else {
                id = "sz" + id;
            }
            return id;
        }).collect(Collectors.toList());
        //将股票集合分片处理
        HttpHeaders headers = new HttpHeaders();
        headers.add("Referer","https://finance.sina.com.cn/stock/");//必须填写，否则数据加载不到
        headers.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
        //请求对象
        HttpEntity<Object> http = new HttpEntity<>(headers);
        Lists.partition(lists,20).forEach(list->{
            System.out.println(list);
            //为每一份动态拼接url地址，然后拉取数据
            String url = stockInfoConfig.getMarketUrl() + String.join(",", list);
            String s = restTemplate.postForObject(url, http, String.class);
            System.out.println("拉取的数据"+s);
            //解析数据，封装pojo
            List info = parserStockInfoUtil.parser4StockOrMarketInfo(s, ParseType.ASHARE);
            log.info("当前解析的数据",info);
            //批量插入
            stockRtInfoMapper.insertBatch(info);

        });
    }

    @Override
    public void collectBlockInfo() {
        //Url地址
        String blockUrl = stockInfoConfig.getBlockUrl();
        HttpHeaders headers = new HttpHeaders();
        //将请求头对象封装到请求对象下
        HttpEntity<Object> http = new HttpEntity<>(headers);
        //发起请求
        String s = restTemplate.postForObject(blockUrl,http, String.class);
//        System.out.println(s);
        //解析封装
        List<StockBlockRtInfo> stockBlocks = parserStockInfoUtil.parse4StockBlock(s);
        Lists.partition(stockBlocks,20).forEach(stockBlock->{
            //批量插入
            stockBlockRtInfoMapper.insertBatch(stockBlock);
        });

    }
}
